package com.metadata_system.common.service;

import com.metadata_system.common.dto.ApiResult;
import com.metadata_system.common.enums.ImageVerifyEventType;
import com.metadata_system.common.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;

@Service
@Slf4j
public class ImageVerifyCodeService {

    @Autowired
    RedisUtil redisUtil;

    @Value("${metadata-system.image-verify.redis-prefix:IMAGE_VERIFY_CODE_}")
    private String redisPrefix = "IMAGE_VERIFY_CODE_";
    // 生成图片宽度
    @Value("${metadata-system.image-verify.image-width:80}")
    private int imageWidth = 80;
    // 生成图片高度
    @Value("${metadata-system.image-verify.image-height:35}")
    private int imageHeight = 35;
    // 图片文字长度
    @Value("${metadata-system.image-verify.code-length:4}")
    private int codeLength = 4;
    // 有效期
    @Value("${metadata-system.image-verify.expired-seconds:3600}")
    private int expiredSeconds = 3600;

    // 生成验证码

    public BufferedImage generate(String deviceId, ImageVerifyEventType eventType) {
        String randCode = RandomStringUtils.randomNumeric(this.codeLength);
        this.redisUtil.setValue(
                this.getKey(deviceId, eventType),
                randCode,
                this.expiredSeconds);
        // 生成,并且返回图片
        return this.generateImage(randCode);
    }

    // 检查验证码

    public ApiResult check(String deviceId, ImageVerifyEventType eventType, String code) {
        String redisKey=this.getKey(deviceId, eventType);
        String redisCode = this.redisUtil.getValue(redisKey, String.class);
        // 清空验证码缓存
        this.redisUtil.del(this.getKey(deviceId, eventType));
        // 有效,且
        if (redisCode!=null && redisCode.equals(code)) {
            return ApiResult.success("图片验证码 正确");
        } else {
//            log.info("redisKey: "+redisKey);
//            log.info("redisCode: "+redisCode);
//            log.info("code: "+code);
            return ApiResult.error("图片验证码 错误");
        }
    }

    private String getKey(String deviceId, ImageVerifyEventType eventType) {
        return this.redisPrefix + eventType.toString().toUpperCase() + "_" + deviceId.toUpperCase();
    }

    /**
     * 生成图片验证码
     *
     * @param randCode 验证码
     * @return
     */
    private BufferedImage generateImage(String randCode) {
        BufferedImage image = new BufferedImage(this.imageWidth, this.imageHeight, BufferedImage.TYPE_INT_RGB);
        Graphics g = image.getGraphics();
        Random random = new Random();
        g.setColor(getRandColor(200, 250));
        g.fillRect(0, 0, this.imageWidth, this.imageHeight);
        g.setFont(new Font("Times New Roman", Font.ITALIC, 32));
        g.setColor(getRandColor(160, 200));

        // 绘制干扰线
        for (int i = 0; i < 155; i++) {
            int x = random.nextInt(this.imageWidth);
            int y = random.nextInt(this.imageHeight);
            int xl = random.nextInt(12);
            int yl = random.nextInt(12);
            g.drawLine(x, y, x + xl, y + yl);
        }

        // 写入文字
        int fontMargin = 15;
        int leftMargin = 8;
        String[] codeArr = randCode.split("");
        for (int i = 0; i < this.codeLength; i++) {
            g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));
            g.drawString(codeArr[i], fontMargin * i + leftMargin, (int) (this.imageHeight * 0.8));
        }

        g.dispose();
        return image;
    }

    /**
     * 随机颜色
     *
     * @param frontColor 前景色
     * @param backColor  背景色
     * @return 随机颜色
     */
    private Color getRandColor(int frontColor, int backColor) {
        Random random = new Random();
        if (frontColor > 255) {
            frontColor = 255;
        }
        if (backColor > 255) {
            backColor = 255;
        }
        int r = frontColor + random.nextInt(backColor - frontColor);
        int g = frontColor + random.nextInt(backColor - frontColor);
        int b = frontColor + random.nextInt(backColor - frontColor);
        return new Color(r, g, b);
    }
}
